#include "types.h"
#include "defs.h"
#include "param.h"
#include "stat.h"
#include "mmu.h"
#include "proc.h"
#include "fs.h"
#include "file.h"
#include "fcntl.h"
#include "sysfile.h"

int debug_switch = 0;

//pde_t *s_pgdir_debug;
struct inode *swapper_inode;
char swapper_inited = 0;

int get_debug_switch()
{
    return debug_switch;
}
void set_debug_switch()
{
    debug_switch = 1;
}


struct inode* swapper_create()
{
  uint off;
  struct inode *ip, *dp;
  char name[DIRSIZ];
  short major = 0, minor = 0;
  short type = T_FILE;
  char path[] = "swap_file";

  if((dp = nameiparent(path, name)) == 0)
    return 0;
  ilock(dp);

  if((ip = dirlookup(dp, name, &off)) != 0){
    iunlockput(dp);
    ilock(ip);
    if(type == T_FILE && ip->type == T_FILE)
      return ip;
    iunlockput(ip);
    return 0;
  }

  if((ip = ialloc(dp->dev, type)) == 0)
    panic("create: ialloc");

  ilock(ip);
  ip->major = major;
  ip->minor = minor;
  ip->nlink = 1;
  iupdate(ip);

  // if(type == T_DIR){  // Create . and .. entries.
  //   dp->nlink++;  // for ".."
  //   iupdate(dp);
  //   // No ip->nlink++ for ".": avoid cyclic ref count.
  //   if(dirlink(ip, ".", ip->inum) < 0 || dirlink(ip, "..", dp->inum) < 0)
  //     panic("create dots");
  // }

  if(dirlink(dp, name, ip->inum) < 0)
    panic("create: dirlink");

  iunlockput(dp);

  return ip;
}

void swapper_init()
{
    if(swapper_inited == 1) return;
    swapper_inited = 1;

    // Create swap file
    //swapper_inode = swapper_create();
    //s_pgdir_debug = setupkvm();
    cprintf("Swapper has been initialized.");
}


// void create_file()
// {
//     char *path;
//     int fd, omode;
//     struct file *f;
//     struct inode *ip;

//     if(argstr(0, &path) < 0 || argint(1, &omode) < 0)
//     return -1;
//     if(omode & O_CREATE){
//         begin_trans();
//         ip = create(path, T_FILE, 0, 0);
//         commit_trans();
//         if(ip == 0)
//             return -1;
//     } else {
//     if((ip = namei(path)) == 0)
//         return -1;
//     ilock(ip);
//     if(ip->type == T_DIR && omode != O_RDONLY){
//       iunlockput(ip);
//       return -1;
//     }
//   }

//   if((f = filealloc()) == 0 || (fd = fdalloc(f)) < 0){
//     if(f)
//       fileclose(f);
//     iunlockput(ip);
//     return -1;
//   }
//   iunlock(ip);

//   f->type = FD_INODE;
//   f->ip = ip;
//   f->off = 0;
//   f->readable = !(omode & O_WRONLY);
//   f->writable = (omode & O_WRONLY) || (omode & O_RDWR);
//   return fd;
// }

void test_writefile()
{
    // int omode;
    // struct file* f;
    // struct inode *ip;
    cprintf("debug switch = %d\n",debug_switch);

    if(debug_switch == 0) return;

    //create_file();
}

void swap_out(struct proc *p)
{
    //(*p)->tf
}

// void
// inituvm(pde_t *pgdir, char *init, uint sz)
// {
//   char *mem;
//   //uint i,j;
//   // uint *pde, *pgtab, *pte, pa;
//   // uint va, *p_pa;
//   // char *v;

//   if(sz >= PGSIZE)
//     panic("inituvm: more than a page");
//   mem = kalloc();
//   memset(mem, 0, PGSIZE);
//   mappages(pgdir, 0, PGSIZE, v2p(mem), PTE_W|PTE_U);


  // mem[0] = 255;

  // pde = &pgdir[PDX(mem)];
  // pgtab = (pte_t*)p2v(PTE_ADDR(*pde));
  // pte = &pgtab[PTX(mem)];
  // pa = PTE_ADDR(*pte);
  // p_pa = (uint*)va;

  // cprintf("[inituvm]\tpgdir\t%x\t%x\tPDX(mem)\t%d\n",pgdir,*pgdir,PDX(mem));
  // cprintf("[inituvm]\tPDX\t%x\t\tPTX\t%x\t%x\n",PDX(mem),PTX(mem), (PDX(mem) << 22) | (PTX(mem) << 12));
  // cprintf("[inituvm]\tva[mem]\t%x\tvalue\t%x\n",mem,*mem);
  // pte = walkpgdir(pgdir, mem, 0);
  // cprintf("[inituvm]\tpde\t%x\t%x\n",pde,*pde);
  // cprintf("[inituvm]\tpgtab\t%x\t%x\n",pgtab,*pgtab);
  // cprintf("[inituvm]\tpte\t%x\t%x\n",pte,*pte);
  // pa = PTE_ADDR(*pte);
  // v = p2v(pa);
  // cprintf("[inituvm]\tpa\t%x\t%x\n",&pa,pa);
  // cprintf("[inituvm]\tv\t%x\t%x\n",v,*v);

  // cprintf("[inituvm]\tva\t%x\t%x\n",&va,va);

  // va = (uint) &pgdir;                       cprintf("[inituvm]\tva\t%x\t\n",va);
  // pde = &pgdir[PDX(va)];                    cprintf("[inituvm]\tpde\t%x\t%x\n",pde,*pde);
  // pgtab = (pte_t*)p2v(PTE_ADDR(*pde));      cprintf("[inituvm]\tpgtab\t%x\t%x\n",pgtab,*pgtab);
  // pte = &pgtab[PTX(va)];                    cprintf("[inituvm]\tpte\t%x\t%x\n",pte,*pte);

  // pa = PTE_ADDR(*pte);
  // p_pa = (uint*)va;
  // cprintf("[inituvm]\tpa\t%x\tp_pa\t%x\n",pa,*p_pa);


 // for(i=0;i<1000*1000*10;i++)
 //   for(j=0;j<1000 *2;j++) {}

//   memmove(mem, init, sz);


// }